import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 储存数据
const state = {
  // 储存共享的购物车数据
  // 页面进入拿数据的时候, 优先获取备份过的旧数据
  cart: uni.getStorageSync('cart') || [],
  token: ''
}

// 修改 state
const mutations = {
  setToken(state, payload) {
    state.token = payload
  },
  addGoods(state, payload) {
    // 查找是否有旧商品 id 相同
    const prod = state.cart.find(item => item.goods_id === payload.goods_id)
    if (prod) {
      // 商品已经添加过, 数据加一即可
      prod.number++
    } else {
      // 数据没加过, 拼接好购物车要用的数据一起记录
      state.cart.push({
        ...payload,
        number: 1,
        isCheck: true
      })
    }
    console.log('vuex 添加商品', state.cart);
    // 数据发生改变应该备份 注意没有了浏览器的 localStorage 等待东西
    // 需要用到小程序接口, 在 uniapp 文档查询即可
    // uni.setStorageSync('cart', state.cart)
  },
  toggleCheck(state, payload) {
    // 接收到点击的商品信息, 要在 state.cart 内部
    // 找到这个商品并修改 isCheck 才行
    const prod = state.cart.find(item => item.goods_id === payload.goods_id)
    // 上面这个函数找到产品列表中id跟传入点击目标一致的对象, 返回了这个对象的引用地址
    prod.isCheck = !prod.isCheck
    // 数据发生改变应该备份 注意没有了浏览器的 localStorage 等待东西
    // 需要用到小程序接口, 在 uniapp 文档查询即可
    // uni.setStorageSync('cart', state.cart)
  },
  // 无论减一还是假意, 跟原来修改选中状态没什么不一样
  // 1. 找到对应商品
  // 2. 修改数据
  minusGoods(state, payload) {
    const prod = state.cart.find(item => item.goods_id === payload.goods_id)
    if (prod) {
      prod.number--
    }
    // uni.setStorageSync('cart', state.cart)
  },
  plusGoods(state, payload) {
    const prod = state.cart.find(item => item.goods_id === payload.goods_id)
    if (prod) {
      prod.number++
    }
    // uni.setStorageSync('cart', state.cart)
  },
  delGoods(state, payload) {
    state.cart = state.cart.filter(item => item.goods_id !== payload.goods_id)
    // uni.setStorageSync('cart', state.cart)
  },
  toggleAllCheck(state, payload) {
    // 这里的 payload 就是希望将所有商品改变的 isCheck 状态
    console.log('接收到希望的全选状态, 将所有商品的状态统一改成一样即可');
    state.cart.forEach(item => {
      item.isCheck = payload
    });
    // 持久化
    // uni.setStorageSync('cart', state.cart)
  },
  // 清理已经购买商品
  clearCart(state) {
    // 这里是购买完成以后, 清理购物车数据的操作
    // 主要清理掉已经勾选的产品(给过钱啦)
    state.cart = state.cart.filter(item => !item.isCheck)
    // uni.setStorageSync('cart', state.cart)
  }
}

// 异步操作
const actions = {
  async login(context) {
    // 获取用户信息
    const [errProfile, resProfile] = await uni.getUserProfile({
      desc: "为了更好服务用户",
    });
    console.log("获取用户信息", resProfile);
    // 获取临时登录通行码
    const [errLogin, resLogin] = await uni.login();
    console.log("获取临时通行码", resLogin);
    // 发送请求获取token
    const { token } = await uni.$u.http.post("/users/wxlogin", {
      ...resProfile,
      ...resLogin,
    });
    console.log("登录成功获取到 token", token);
    context.commit('setToken', token)
  }
}

// 派生数据, 共享的 omputed 计算属性
const getters = {
  // 这里可以声明一些基于  state 的派生数据(就像计算属性, 自己本身不存在, 基于别的数据计算出来)
  // totalType(state) {
  //   return state.cart.length
  // }
  // 简化成箭头函数如下
  // 总品类, 显示在商品详情页
  totalType: state => state.cart.length,
  // 盘算列表中所有商品 isCheck 都为真
  // every 可以给定一个回调
  // 自动遍历所有的元素, 执行回调
  // 如果所有回调的返回值都是  true, 最终结果就是 true
  // 只要有一个为 false 最终结果就是false
  // 用来检查一个数组中是否每个元素都符合条件的方法
  // bugfix: every 在空数组中永远返回 true 所以需要同时判断数量
  isAllCheck: state => state.cart.length > 0 && state.cart.every(item => item.isCheck),
  totalPrice: state => {
    // 遍历列表, 每个元素如果被选中, 就将数量乘以价格累加起来
    let res = 0

    state.cart.forEach(item => {
      if (item.isCheck) {
        res += item.goods_price * item.number
      }
    });

    return res
  },
  // 总数量, 显示在购物车
  totalNumber: state => {
    let res = 0
    state.cart.forEach(item => {
      // 遍历列表, 每个元素如果被选中, 就将数量累加起来
      if (item.isCheck) {
        res += item.number
      }
    });
    return res
  },
  productCheck: state => state.cart.filter(item => item.isCheck)
}

const store = new Vuex.Store({
  state,
  mutations,
  actions,
  // getters 要在创建 store 实例的时候带上
  getters
})

// 这里可以订阅 store 实例的 mutations
store.subscribe((mutations, state) => {
  console.log('统一监听mutations操作');
  console.log(mutations);
  console.log(state);
  // 所有的mutations触发后都会调用这个函数实现数据持久化
  uni.setStorageSync('cart', state.cart)
})

export default store